home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / ftp-rl.taz / ftp-rl / ftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-07  |  30.2 KB  |  1,461 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)ftp.c    5.36 (Berkeley) 6/29/90";
  22. #endif /* not lint */
  23.  
  24. #include <sys/param.h>
  25. #include <sys/stat.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/socket.h>
  28. #include <sys/time.h>
  29. #include <sys/file.h>
  30.  
  31. #include <netinet/in.h>
  32. #include <netinet/in_systm.h>
  33. #include <netinet/ip.h>
  34. #include <arpa/ftp.h>
  35. #include <arpa/telnet.h>
  36.  
  37. #include <stdio.h>
  38. #include <signal.h>
  39. #include <errno.h>
  40. #include <netdb.h>
  41. #include <fcntl.h>
  42. #include <pwd.h>
  43. #include <varargs.h>
  44.  
  45. #include "ftp_var.h"
  46.  
  47. struct    sockaddr_in hisctladdr;
  48. struct    sockaddr_in data_addr;
  49. int    data = -1;
  50. int    abrtflag = 0;
  51. int    ptflag = 0;
  52. struct    sockaddr_in myctladdr;
  53. uid_t    getuid();
  54. sig_t    lostpeer();
  55. off_t    restart_point = 0;
  56.  
  57. extern char *strerror();
  58. extern int connected, errno;
  59.  
  60. FILE    *cin, *cout;
  61. FILE    *dataconn();
  62.  
  63. char *
  64. hookup(host, port)
  65.     char *host;
  66.     int port;
  67. {
  68.     register struct hostent *hp = 0;
  69.     int s, len, tos;
  70.     static char hostnamebuf[80];
  71.  
  72.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  73.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  74.     if (hisctladdr.sin_addr.s_addr != -1) {
  75.         hisctladdr.sin_family = AF_INET;
  76.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  77.     } else {
  78.         hp = gethostbyname(host);
  79.         if (hp == NULL) {
  80.             fprintf(stderr, "ftp: %s: ", host);
  81.             herror((char *)NULL);
  82.             code = -1;
  83.             return((char *) 0);
  84.         }
  85.         hisctladdr.sin_family = hp->h_addrtype;
  86.         bcopy(hp->h_addr,
  87.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  88.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  89.     }
  90.     hostname = hostnamebuf;
  91.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  92.     if (s < 0) {
  93.         perror("ftp: socket");
  94.         code = -1;
  95.         return (0);
  96.     }
  97.     hisctladdr.sin_port = port;
  98.     while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
  99.         if (hp && 0 /*hp->h_addr_list[1]*/) {
  100.             int oerrno = errno;
  101.             extern char *inet_ntoa();
  102.  
  103.             fprintf(stderr, "ftp: connect to address %s: ",
  104.                 inet_ntoa(hisctladdr.sin_addr));
  105.             errno = oerrno;
  106.             perror((char *) 0);
  107.             /*hp->h_addr_list++;*/
  108.             /* This can't work because we don't have an
  109.              * h_addr_list in our struct hostent.
  110.              * Actually, maybe we do, but <netdb.h> doesn't
  111.              * show it.
  112.              */
  113.             bcopy(hp->h_addr,
  114.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  115.             fprintf(stdout, "Trying %s...\n",
  116.                 inet_ntoa(hisctladdr.sin_addr));
  117.             (void) close(s);
  118.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  119.             if (s < 0) {
  120.                 perror("ftp: socket");
  121.                 code = -1;
  122.                 return (0);
  123.             }
  124.             continue;
  125.         }
  126.         perror("ftp: connect");
  127.         code = -1;
  128.         goto bad;
  129.     }
  130.     len = sizeof (myctladdr);
  131.     if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
  132.         perror("ftp: getsockname");
  133.         code = -1;
  134.         goto bad;
  135.     }
  136. #ifdef IP_TOS
  137.     tos = IPTOS_LOWDELAY;
  138.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  139.         perror("ftp: setsockopt TOS (ignored)");
  140. #endif
  141.     cin = fdopen(s, "r");
  142.     cout = fdopen(s, "w");
  143.     if (cin == NULL || cout == NULL) {
  144.         fprintf(stderr, "ftp: fdopen failed.\n");
  145.         if (cin)
  146.             (void) fclose(cin);
  147.         if (cout)
  148.             (void) fclose(cout);
  149.         code = -1;
  150.         goto bad;
  151.     }
  152.     if (verbose)
  153.         printf("Connected to %s.\n", hostname);
  154.     if (getreply(0) > 2) {     /* read startup message from server */
  155.         if (cin)
  156.             (void) fclose(cin);
  157.         if (cout)
  158.             (void) fclose(cout);
  159.         code = -1;
  160.         goto bad;
  161.     }
  162. #ifdef SO_OOBINLINE
  163.     {
  164.     int on = 1;
  165.  
  166.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
  167.         < 0 && debug) {
  168.             perror("ftp: setsockopt");
  169.         }
  170.     }
  171. #endif /* SO_OOBINLINE */
  172.  
  173.     return (hostname);
  174. bad:
  175.     (void) close(s);
  176.     return ((char *)0);
  177. }
  178.  
  179. login(host)
  180.     char *host;
  181. {
  182.     char tmp[80];
  183.     char *user, *pass, *acct, *getlogin(), *getpass();
  184.     int n, aflag = 0;
  185.  
  186.     user = pass = acct = 0;
  187.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  188.         code = -1;
  189.         return(0);
  190.     }
  191.     while (user == NULL) {
  192.         char *myname = getlogin();
  193.  
  194.         if (myname == NULL) {
  195.             struct passwd *pp = getpwuid(getuid());
  196.  
  197.             if (pp != NULL)
  198.                 myname = pp->pw_name;
  199.         }
  200.         if (myname)
  201.             printf("Name (%s:%s): ", host, myname);
  202.         else
  203.             printf("Name (%s): ", host);
  204.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  205.         tmp[strlen(tmp) - 1] = '\0';
  206.         if (*tmp == '\0')
  207.             user = myname;
  208.         else
  209.             user = tmp;
  210.     }
  211.     n = command("USER %s", user);
  212.     if (n == CONTINUE) {
  213.         if (pass == NULL)
  214.             pass = getpass("Password:");
  215.         n = command("PASS %s", pass);
  216.     }
  217.     if (n == CONTINUE) {
  218.         aflag++;
  219.         acct = getpass("Account:");
  220.         n = command("ACCT %s", acct);
  221.     }
  222.     if (n != COMPLETE) {
  223.         fprintf(stderr, "Login failed.\n");
  224.         return (0);
  225.     }
  226.     if (!aflag && acct != NULL)
  227.         (void) command("ACCT %s", acct);
  228.     if (proxy)
  229.         return(1);
  230.     for (n = 0; n < macnum; ++n) {
  231.         if (!strcmp("init", macros[n].mac_name)) {
  232.             (void) strcpy(line, "$init");
  233.             makeargv();
  234.             domacro(margc, margv);
  235.             break;
  236.         }
  237.     }
  238.     return (1);
  239. }
  240.  
  241. void
  242. cmdabort()
  243. {
  244.     extern jmp_buf ptabort;
  245.  
  246.     printf("\n");
  247.     (void) fflush(stdout);
  248.     abrtflag++;
  249.     if (ptflag)
  250.         longjmp(ptabort,1);
  251. }
  252.  
  253. /*VARARGS*/
  254. command(va_alist)
  255. va_dcl
  256. {
  257.     va_list ap;
  258.     char *fmt;
  259.     int r;
  260.     sig_t oldintr;
  261.     void cmdabort();
  262.  
  263.     abrtflag = 0;
  264.     if (debug) {
  265.         printf("---> ");
  266.         va_start(ap);
  267.         fmt = va_arg(ap, char *);
  268.         if (strncmp("PASS ", fmt, 5) == 0)
  269.             printf("PASS XXXX");
  270.         else 
  271.             vfprintf(stdout, fmt, ap);
  272.         va_end(ap);
  273.         printf("\n");
  274.         (void) fflush(stdout);
  275.     }
  276.     if (cout == NULL) {
  277.         perror ("No control connection for command");
  278.         code = -1;
  279.         return (0);
  280.     }
  281.     oldintr = signal(SIGINT, cmdabort);
  282.     va_start(ap);
  283.     fmt = va_arg(ap, char *);
  284.     vfprintf(cout, fmt, ap);
  285.     va_end(ap);
  286.     fprintf(cout, "\r\n");
  287.     (void) fflush(cout);
  288.     cpend = 1;
  289.     r = getreply(!strcmp(fmt, "QUIT"));
  290.     if (abrtflag && oldintr != SIG_IGN)
  291.         signal(SIGINT, cmdabort);/* (*oldintr)(); */
  292.     (void) signal(SIGINT, oldintr);
  293.     return(r);
  294. }
  295.  
  296. char reply_string[BUFSIZ];        /* last line of previous reply */
  297.  
  298. #include <ctype.h>
  299.  
  300. getreply(expecteof)
  301.     int expecteof;
  302. {
  303.     register int c, n;
  304.     register int dig;
  305.     register char *cp;
  306.     int originalcode = 0, continuation = 0;
  307.     sig_t oldintr;
  308.     int pflag = 0;
  309.     char *pt = pasv;
  310.     void cmdabort();
  311.  
  312.     oldintr = signal(SIGINT, cmdabort);
  313.     for (;;) {
  314.         dig = n = code = 0;
  315.         cp = reply_string;
  316.         while ((c = getc(cin)) != '\n') {
  317.             if (c == IAC) {     /* handle telnet commands */
  318.                 switch (c = getc(cin)) {
  319.                 case WILL:
  320.                 case WONT:
  321.                     c = getc(cin);
  322.                     fprintf(cout, "%c%c%c", IAC, DONT, c);
  323.                     (void) fflush(cout);
  324.                     break;
  325.                 case DO:
  326.                 case DONT:
  327.                     c = getc(cin);
  328.                     fprintf(cout, "%c%c%c", IAC, WONT, c);
  329.                     (void) fflush(cout);
  330.                     break;
  331.                 default:
  332.                     break;
  333.                 }
  334.                 continue;
  335.             }
  336.             dig++;
  337.             if (c == EOF) {
  338.                 if (expecteof) {
  339.                     (void) signal(SIGINT,oldintr);
  340.                     code = 221;
  341.                     return (0);
  342.                 }
  343.                 lostpeer();
  344.                 if (verbose) {
  345.                     printf("421 Service not available, remote server has closed connection\n");
  346.                     (void) fflush(stdout);
  347.                 }
  348.                 code = 421;
  349.                 return(4);
  350.             }
  351.             if (c != '\r' && (verbose > 0 ||
  352.                 (verbose > -1 && n == '5' && dig > 4))) {
  353.                 if (proxflag &&
  354.                    (dig == 1 || dig == 5 && verbose == 0))
  355.                     printf("%s:",hostname);
  356.                 (void) putchar(c);
  357.             }
  358.             if (dig < 4 && isdigit(c))
  359.                 code = code * 10 + (c - '0');
  360.             if (!pflag && code == 227)
  361.                 pflag = 1;
  362.             if (dig > 4 && pflag == 1 && isdigit(c))
  363.                 pflag = 2;
  364.             if (pflag == 2) {
  365.                 if (c != '\r' && c != ')')
  366.                     *pt++ = c;
  367.                 else {
  368.                     *pt = '\0';
  369.                     pflag = 3;
  370.                 }
  371.             }
  372.             if (dig == 4 && c == '-') {
  373.                 if (continuation)
  374.                     code = 0;
  375.                 continuation++;
  376.             }
  377.             if (n == 0)
  378.                 n = c;
  379.             if (cp < &reply_string[sizeof(reply_string) - 1])
  380.                 *cp++ = c;
  381.         }
  382.         if (verbose > 0 || verbose > -1 && n == '5') {
  383.             (void) putchar(c);
  384.             (void) fflush (stdout);
  385.         }
  386.         if (continuation && code != originalcode) {
  387.             if (originalcode == 0)
  388.                 originalcode = code;
  389.             continue;
  390.         }
  391.         *cp = '\0';
  392.         if (n != '1')
  393.             cpend = 0;
  394.         (void) signal(SIGINT,oldintr);
  395.         if (code == 421 || originalcode == 421)
  396.             lostpeer();
  397.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  398.             signal(SIGINT, cmdabort);/* (*oldintr)();*/
  399.         return (n - '0');
  400.     }
  401. }
  402.  
  403. empty(mask, sec)
  404.     /*struct*/ fd_set *mask;
  405.     int sec;
  406. {
  407.     struct timeval t;
  408.  
  409.     t.tv_sec = (long) sec;
  410.     t.tv_usec = 0;
  411.     return(select(32, mask, (/*struct*/ fd_set *) 0, (/*struct*/ fd_set *) 0, &t));
  412. }
  413.  
  414. jmp_buf    sendabort;
  415.  
  416. void
  417. abortsend()
  418. {
  419.  
  420.     mflag = 0;
  421.     abrtflag = 0;
  422.     printf("\nsend aborted\nwaiting for remote to finish abort\n");
  423.     (void) fflush(stdout);
  424.     longjmp(sendabort, 1);
  425. }
  426.  
  427. #define HASHBYTES 1024
  428.  
  429. sendrequest(cmd, local, remote, printnames)
  430.     char *cmd, *local, *remote;
  431.     int printnames;
  432. {
  433.     struct stat st;
  434.     struct timeval start, stop;
  435.     register int c, d;
  436.     FILE *fin, *dout = 0, *popen();
  437.     int (*closefunc)(), pclose(), fclose();
  438.     sig_t oldintr, oldintp;
  439.     long bytes = 0, hashbytes = HASHBYTES;
  440.     char *lmode, buf[BUFSIZ], *bufp;
  441.     void abortsend();
  442.  
  443.     if (verbose && printnames) {
  444.         if (local && *local != '-')
  445.             printf("local: %s ", local);
  446.         if (remote)
  447.             printf("remote: %s\n", remote);
  448.     }
  449.     if (proxy) {
  450.         proxtrans(cmd, local, remote);
  451.         return;
  452.     }
  453.     if (curtype != type)
  454.         changetype(type, 0);
  455.     closefunc = NULL;
  456.     oldintr = NULL;
  457.     oldintp = NULL;
  458.     lmode = "w";
  459.     if (setjmp(sendabort)) {
  460.         while (cpend) {
  461.             (void) getreply(0);
  462.         }
  463.         if (data >= 0) {
  464.             (void) close(data);
  465.             data = -1;
  466.         }
  467.         if (oldintr)
  468.             (void) signal(SIGINT,oldintr);
  469.         if (oldintp)
  470.             (void) signal(SIGPIPE,oldintp);
  471.         code = -1;
  472.         return;
  473.     }
  474.     oldintr = signal(SIGINT, abortsend);
  475.     if (strcmp(local, "-") == 0)
  476.         fin = stdin;
  477.     else if (*local == '|') {
  478.         oldintp = signal(SIGPIPE,SIG_IGN);
  479.         fin = popen(local + 1, "r");
  480.         if (fin == NULL) {
  481.             perror(local + 1);
  482.             (void) signal(SIGINT, oldintr);
  483.             (void) signal(SIGPIPE, oldintp);
  484.             code = -1;
  485.             return;
  486.         }
  487.         closefunc = pclose;
  488.     } else {
  489.         fin = fopen(local, "r");
  490.         if (fin == NULL) {
  491.             fprintf(stderr, "local: %s: %s\n", local,
  492.                 strerror(errno));
  493.             (void) signal(SIGINT, oldintr);
  494.             code = -1;
  495.             return;
  496.         }
  497.         closefunc = fclose;
  498.         if (fstat(fileno(fin), &st) < 0 ||
  499.             (st.st_mode&S_IFMT) != S_IFREG) {
  500.             fprintf(stdout, "%s: not a plain file.\n", local);
  501.             (void) signal(SIGINT, oldintr);
  502.             fclose(fin);
  503.             code = -1;
  504.             return;
  505.         }
  506.     }
  507.     if (initconn()) {
  508.         (void) signal(SIGINT, oldintr);
  509.         if (oldintp)
  510.             (void) signal(SIGPIPE, oldintp);
  511.         code = -1;
  512.         if (closefunc != NULL)
  513.             (*closefunc)(fin);
  514.         return;
  515.     }
  516.     if (setjmp(sendabort))
  517.         goto abort;
  518.  
  519.     if (restart_point &&
  520.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  521.         if (fseek(fin, (long) restart_point, 0) < 0) {
  522.             fprintf(stderr, "local: %s: %s\n", local,
  523.                 strerror(errno));
  524.             restart_point = 0;
  525.             if (closefunc != NULL)
  526.                 (*closefunc)(fin);
  527.             return;
  528.         }
  529.         if (command("REST %ld", (long) restart_point)
  530.             != CONTINUE) {
  531.             restart_point = 0;
  532.             if (closefunc != NULL)
  533.                 (*closefunc)(fin);
  534.             return;
  535.         }
  536.         restart_point = 0;
  537.         lmode = "r+w";
  538.     }
  539.     if (remote) {
  540.         if (command("%s %s", cmd, remote) != PRELIM) {
  541.             (void) signal(SIGINT, oldintr);
  542.             if (oldintp)
  543.                 (void) signal(SIGPIPE, oldintp);
  544.             if (closefunc != NULL)
  545.                 (*closefunc)(fin);
  546.             return;
  547.         }
  548.     } else
  549.         if (command("%s", cmd) != PRELIM) {
  550.             (void) signal(SIGINT, oldintr);
  551.             if (oldintp)
  552.                 (void) signal(SIGPIPE, oldintp);
  553.             if (closefunc != NULL)
  554.                 (*closefunc)(fin);
  555.             return;
  556.         }
  557.     dout = dataconn(lmode);
  558.     if (dout == NULL)
  559.         goto abort;
  560.     (void) gettimeofday(&start, (struct timezone *)0);
  561.     oldintp = signal(SIGPIPE, SIG_IGN);
  562.     switch (curtype) {
  563.  
  564.     case TYPE_I:
  565.     case TYPE_L:
  566.         errno = d = 0;
  567.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  568.             bytes += c;
  569.             for (bufp = buf; c > 0; c -= d, bufp += d)
  570.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  571.                     break;
  572.             if (hash) {
  573.                 while (bytes >= hashbytes) {
  574.                     (void) putchar('#');
  575.                     hashbytes += HASHBYTES;
  576.                 }
  577.                 (void) fflush(stdout);
  578.             }
  579.         }
  580.         if (hash && bytes > 0) {
  581.             if (bytes < HASHBYTES)
  582.                 (void) putchar('#');
  583.             (void) putchar('\n');
  584.             (void) fflush(stdout);
  585.         }
  586.         if (c < 0)
  587.             fprintf(stderr, "local: %s: %s\n", local,
  588.                 strerror(errno));
  589.         if (d <= 0) {
  590.             if (d == 0)
  591.                 fprintf(stderr, "netout: write returned 0?\n");
  592.             else if (errno != EPIPE) 
  593.                 perror("netout");
  594.             bytes = -1;
  595.         }
  596.         break;
  597.  
  598.     case TYPE_A:
  599.         while ((c = getc(fin)) != EOF) {
  600.             if (c == '\n') {
  601.                 while (hash && (bytes >= hashbytes)) {
  602.                     (void) putchar('#');
  603.                     (void) fflush(stdout);
  604.                     hashbytes += HASHBYTES;
  605.                 }
  606.                 if (ferror(dout))
  607.                     break;
  608.                 (void) putc('\r', dout);
  609.                 bytes++;
  610.             }
  611.             (void) putc(c, dout);
  612.             bytes++;
  613.     /*        if (c == '\r') {                  */
  614.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  615.     /*            bytes++;                */
  616.     /*        }                                      */    
  617.         }
  618.         if (hash) {
  619.             if (bytes < hashbytes)
  620.                 (void) putchar('#');
  621.             (void) putchar('\n');
  622.             (void) fflush(stdout);
  623.         }
  624.         if (ferror(fin))
  625.             fprintf(stderr, "local: %s: %s\n", local,
  626.                 strerror(errno));
  627.         if (ferror(dout)) {
  628.             if (errno != EPIPE)
  629.                 perror("netout");
  630.             bytes = -1;
  631.         }
  632.         break;
  633.     }
  634.     (void) gettimeofday(&stop, (struct timezone *)0);
  635.     if (closefunc != NULL)
  636.         (*closefunc)(fin);
  637.     (void) fclose(dout);
  638.     (void) getreply(0);
  639.     (void) signal(SIGINT, oldintr);
  640.     if (oldintp)
  641.         (void) signal(SIGPIPE, oldintp);
  642.     if (bytes > 0)
  643.         ptransfer("sent", bytes, &start, &stop);
  644.     return;
  645. abort:
  646.     (void) gettimeofday(&stop, (struct timezone *)0);
  647.     (void) signal(SIGINT, oldintr);
  648.     if (oldintp)
  649.         (void) signal(SIGPIPE, oldintp);
  650.     if (!cpend) {
  651.         code = -1;
  652.         return;
  653.     }
  654.     if (data >= 0) {
  655.         (void) close(data);
  656.         data = -1;
  657.     }
  658.     if (dout)
  659.         (void) fclose(dout);
  660.     (void) getreply(0);
  661.     code = -1;
  662.     if (closefunc != NULL && fin != NULL)
  663.         (*closefunc)(fin);
  664.     if (bytes > 0)
  665.         ptransfer("sent", bytes, &start, &stop);
  666. }
  667.  
  668. jmp_buf    recvabort;
  669.  
  670. void
  671. abortrecv()
  672. {
  673.  
  674.     mflag = 0;
  675.     abrtflag = 0;
  676.     printf("\nreceive aborted\nwaiting for remote to finish abort\n");
  677.     (void) fflush(stdout);
  678.     longjmp(recvabort, 1);
  679. }
  680.  
  681. recvrequest(cmd, local, remote, lmode, printnames)
  682.     char *cmd, *local, *remote, *lmode;
  683. {
  684.     FILE *fout, *din = 0, *popen();
  685.     int (*closefunc)(), pclose(), fclose();
  686.     sig_t oldintr, oldintp;
  687.     int is_retr, tcrflag, bare_lfs = 0;
  688.     char *gunique();
  689.     static int bufsize;
  690.     static char *buf;
  691.     long bytes = 0, hashbytes = HASHBYTES;
  692.     register int c, d;
  693.     struct timeval start, stop;
  694.     struct stat st;
  695.     off_t lseek();
  696.     void abortrecv();
  697.     char *malloc();
  698.  
  699.     is_retr = strcmp(cmd, "RETR") == 0;
  700.     if (is_retr && verbose && printnames) {
  701.         if (local && *local != '-')
  702.             printf("local: %s ", local);
  703.         if (remote)
  704.             printf("remote: %s\n", remote);
  705.     }
  706.     if (proxy && is_retr) {
  707.         proxtrans(cmd, local, remote);
  708.         return;
  709.     }
  710.     closefunc = NULL;
  711.     oldintr = NULL;
  712.     oldintp = NULL;
  713.     tcrflag = !crflag && is_retr;
  714.     if (setjmp(recvabort)) {
  715.         while (cpend) {
  716.             (void) getreply(0);
  717.         }
  718.         if (data >= 0) {
  719.             (void) close(data);
  720.             data = -1;
  721.         }
  722.         if (oldintr)
  723.             (void) signal(SIGINT, oldintr);
  724.         code = -1;
  725.         return;
  726.     }
  727.     oldintr = signal(SIGINT, abortrecv);
  728.     if (strcmp(local, "-") && *local != '|') {
  729.         if (access(local, 2) < 0) {
  730.             char *dir = rindex(local, '/');
  731.  
  732.             if (errno != ENOENT && errno != EACCES) {
  733.                 fprintf(stderr, "local: %s: %s\n", local,
  734.                     strerror(errno));
  735.                 (void) signal(SIGINT, oldintr);
  736.                 code = -1;
  737.                 return;
  738.             }
  739.             if (dir != NULL)
  740.                 *dir = 0;
  741.             d = access(dir ? local : ".", 2);
  742.             if (dir != NULL)
  743.                 *dir = '/';
  744.             if (d < 0) {
  745.                 fprintf(stderr, "local: %s: %s\n", local,
  746.                     strerror(errno));
  747.                 (void) signal(SIGINT, oldintr);
  748.                 code = -1;
  749.                 return;
  750.             }
  751.             if (!runique && errno == EACCES &&
  752.                 chmod(local, 0600) < 0) {
  753.                 fprintf(stderr, "local: %s: %s\n", local,
  754.                     strerror(errno));
  755.                 (void) signal(SIGINT, oldintr);
  756.                 (void) signal(SIGINT, oldintr);
  757.                 code = -1;
  758.                 return;
  759.             }
  760.             if (runique && errno == EACCES &&
  761.                (local = gunique(local)) == NULL) {
  762.                 (void) signal(SIGINT, oldintr);
  763.                 code = -1;
  764.                 return;
  765.             }
  766.         }
  767.         else if (runique && (local = gunique(local)) == NULL) {
  768.             (void) signal(SIGINT, oldintr);
  769.             code = -1;
  770.             return;
  771.         }
  772.     }
  773.     if (!is_retr) {
  774.         if (curtype != TYPE_A)
  775.             changetype(TYPE_A, 0);
  776.     } else if (curtype != type)
  777.         changetype(type, 0);
  778.     if (initconn()) {
  779.         (void) signal(SIGINT, oldintr);
  780.         code = -1;
  781.         return;
  782.     }
  783.     if (setjmp(recvabort))
  784.         goto abort;
  785.     if (is_retr && restart_point &&
  786.         command("REST %ld", (long) restart_point) != CONTINUE)
  787.         return;
  788.     if (remote) {
  789.         if (command("%s %s", cmd, remote) != PRELIM) {
  790.             (void) signal(SIGINT, oldintr);
  791.             return;
  792.         }
  793.     } else {
  794.         if (command("%s", cmd) != PRELIM) {
  795.             (void) signal(SIGINT, oldintr);
  796.             return;
  797.         }
  798.     }
  799.     din = dataconn("r");
  800.     if (din == NULL)
  801.         goto abort;
  802.     if (strcmp(local, "-") == 0)
  803.         fout = stdout;
  804.     else if (*local == '|') {
  805.         oldintp = signal(SIGPIPE, SIG_IGN);
  806.         fout = popen(local + 1, "w");
  807.         if (fout == NULL) {
  808.             perror(local+1);
  809.             goto abort;
  810.         }
  811.         closefunc = pclose;
  812.     } else {
  813.         fout = fopen(local, lmode);
  814.         if (fout == NULL) {
  815.             fprintf(stderr, "local: %s: %s\n", local,
  816.                 strerror(errno));
  817.             goto abort;
  818.         }
  819.         closefunc = fclose;
  820.     }
  821.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  822.         st.st_blksize = BUFSIZ;
  823.     if (st.st_blksize > bufsize) {
  824.         if (buf)
  825.             (void) free(buf);
  826.         buf = malloc((unsigned)st.st_blksize);
  827.         if (buf == NULL) {
  828.             perror("malloc");
  829.             bufsize = 0;
  830.             goto abort;
  831.         }
  832.         bufsize = st.st_blksize;
  833.     }
  834.     (void) gettimeofday(&start, (struct timezone *)0);
  835.     switch (curtype) {
  836.  
  837.     case TYPE_I:
  838.     case TYPE_L:
  839.         if (restart_point &&
  840.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  841.             fprintf(stderr, "local: %s: %s\n", local,
  842.                 strerror(errno));
  843.             if (closefunc != NULL)
  844.                 (*closefunc)(fout);
  845.             return;
  846.         }
  847.         errno = d = 0;
  848.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  849.             if ((d = write(fileno(fout), buf, c)) != c)
  850.                 break;
  851.             bytes += c;
  852.             if (hash) {
  853.                 while (bytes >= hashbytes) {
  854.                     (void) putchar('#');
  855.                     hashbytes += HASHBYTES;
  856.                 }
  857.                 (void) fflush(stdout);
  858.             }
  859.         }
  860.         if (hash && bytes > 0) {
  861.             if (bytes < HASHBYTES)
  862.                 (void) putchar('#');
  863.             (void) putchar('\n');
  864.             (void) fflush(stdout);
  865.         }
  866.         if (c < 0) {
  867.             if (errno != EPIPE)
  868.                 perror("netin");
  869.             bytes = -1;
  870.         }
  871.         if (d < c) {
  872.             if (d < 0)
  873.                 fprintf(stderr, "local: %s: %s\n", local,
  874.                     strerror(errno));
  875.             else
  876.                 fprintf(stderr, "%s: short write\n", local);
  877.         }
  878.         break;
  879.  
  880.     case TYPE_A:
  881.         if (restart_point) {
  882.             register int i, n, ch;
  883.  
  884.             if (fseek(fout, 0L, L_SET) < 0)
  885.                 goto done;
  886.             n = restart_point;
  887.             for (i = 0; i++ < n;) {
  888.                 if ((ch = getc(fout)) == EOF)
  889.                     goto done;
  890.                 if (ch == '\n')
  891.                     i++;
  892.             }
  893.             if (fseek(fout, 0L, L_INCR) < 0) {
  894. done:
  895.                 fprintf(stderr, "local: %s: %s\n", local,
  896.                     strerror(errno));
  897.                 if (closefunc != NULL)
  898.                     (*closefunc)(fout);
  899.                 return;
  900.             }
  901.         }
  902.         while ((c = getc(din)) != EOF) {
  903.             if (c == '\n')
  904.                 bare_lfs++;
  905.             while (c == '\r') {
  906.                 while (hash && (bytes >= hashbytes)) {
  907.                     (void) putchar('#');
  908.                     (void) fflush(stdout);
  909.                     hashbytes += HASHBYTES;
  910.                 }
  911.                 bytes++;
  912.                 if ((c = getc(din)) != '\n' || tcrflag) {
  913.                     if (ferror(fout))
  914.                         goto break2;
  915.                     (void) putc('\r', fout);
  916.                     if (c == '\0') {
  917.                         bytes++;
  918.                         goto contin2;
  919.                     }
  920.                     if (c == EOF)
  921.                         goto contin2;
  922.                 }
  923.             }
  924.             (void) putc(c, fout);
  925.             bytes++;
  926.     contin2:    ;
  927.         }
  928. break2:
  929.         if (bare_lfs) {
  930.             printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
  931.             printf("File may not have transferred correctly.\n");
  932.         }
  933.         if (hash) {
  934.             if (bytes < hashbytes)
  935.                 (void) putchar('#');
  936.             (void) putchar('\n');
  937.             (void) fflush(stdout);
  938.         }
  939.         if (ferror(din)) {
  940.             if (errno != EPIPE)
  941.                 perror("netin");
  942.             bytes = -1;
  943.         }
  944.         if (ferror(fout))
  945.             fprintf(stderr, "local: %s: %s\n", local,
  946.                 strerror(errno));
  947.         break;
  948.     }
  949.     if (closefunc != NULL)
  950.         (*closefunc)(fout);
  951.     (void) signal(SIGINT, oldintr);
  952.     if (oldintp)
  953.         (void) signal(SIGPIPE, oldintp);
  954.     (void) gettimeofday(&stop, (struct timezone *)0);
  955.     (void) fclose(din);
  956.     (void) getreply(0);
  957.     if (bytes > 0 && is_retr)
  958.         ptransfer("received", bytes, &start, &stop);
  959.     return;
  960. abort:
  961.  
  962. /* abort using RFC959 recommended IP,SYNC sequence  */
  963.  
  964.     (void) gettimeofday(&stop, (struct timezone *)0);
  965.     if (oldintp)
  966.         (void) signal(SIGPIPE, oldintr);
  967.     (void) signal(SIGINT, SIG_IGN);
  968.     if (!cpend) {
  969.         code = -1;
  970.         (void) signal(SIGINT, oldintr);
  971.         return;
  972.     }
  973.  
  974.     abort_remote(din);
  975.     code = -1;
  976.     if (data >= 0) {
  977.         (void) close(data);
  978.         data = -1;
  979.     }
  980.     if (closefunc != NULL && fout != NULL)
  981.         (*closefunc)(fout);
  982.     if (din)
  983.         (void) fclose(din);
  984.     if (bytes > 0)
  985.         ptransfer("received", bytes, &start, &stop);
  986.     (void) signal(SIGINT, oldintr);
  987. }
  988.  
  989. /*
  990.  * Need to start a listen on the data channel before we send the command,
  991.  * otherwise the server's connect may fail.
  992.  */
  993. initconn()
  994. {
  995.     register char *p, *a;
  996.     int result, len, tmpno = 0;
  997.     int on = 1;
  998.  
  999. noport:
  1000.     data_addr = myctladdr;
  1001.     if (sendport)
  1002.         data_addr.sin_port = 0;    /* let system pick one */ 
  1003.     if (data != -1)
  1004.         (void) close(data);
  1005.     data = socket(AF_INET, SOCK_STREAM, 0);
  1006.     if (data < 0) {
  1007.         perror("ftp: socket");
  1008.         if (tmpno)
  1009.             sendport = 1;
  1010.         return (1);
  1011.     }
  1012.     if (!sendport)
  1013.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1014.             perror("ftp: setsockopt (reuse address)");
  1015.             goto bad;
  1016.         }
  1017.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1018.         perror("ftp: bind");
  1019.         goto bad;
  1020.     }
  1021.     if (options & SO_DEBUG &&
  1022.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1023.         perror("ftp: setsockopt (ignored)");
  1024.     len = sizeof (data_addr);
  1025.     if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
  1026.         perror("ftp: getsockname");
  1027.         goto bad;
  1028.     }
  1029.     if (listen(data, 1) < 0)
  1030.         perror("ftp: listen");
  1031.     if (sendport) {
  1032.         a = (char *)&data_addr.sin_addr;
  1033.         p = (char *)&data_addr.sin_port;
  1034. #define    UC(b)    (((int)b)&0xff)
  1035.         result =
  1036.             command("PORT %d,%d,%d,%d,%d,%d",
  1037.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1038.               UC(p[0]), UC(p[1]));
  1039.         if (result == ERROR && sendport == -1) {
  1040.             sendport = 0;
  1041.             tmpno = 1;
  1042.             goto noport;
  1043.         }
  1044.         return (result != COMPLETE);
  1045.     }
  1046.     if (tmpno)
  1047.         sendport = 1;
  1048. #ifdef IP_TOS
  1049.     on = IPTOS_THROUGHPUT;
  1050.     if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
  1051.         perror("ftp: setsockopt TOS (ignored)");
  1052. #endif
  1053.     return (0);
  1054. bad:
  1055.     (void) close(data), data = -1;
  1056.     if (tmpno)
  1057.         sendport = 1;
  1058.     return (1);
  1059. }
  1060.  
  1061. FILE *
  1062. dataconn(lmode)
  1063.     char *lmode;
  1064. {
  1065.     struct sockaddr_in from;
  1066.     int s, fromlen = sizeof (from), tos;
  1067.  
  1068.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1069.     if (s < 0) {
  1070.         perror("ftp: accept");
  1071.         (void) close(data), data = -1;
  1072.         return (NULL);
  1073.     }
  1074.     (void) close(data);
  1075.     data = s;
  1076. #ifdef IP_TOS
  1077.     tos = IPTOS_THROUGHPUT;
  1078.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  1079.         perror("ftp: setsockopt TOS (ignored)");
  1080. #endif
  1081.     return (fdopen(data, lmode));
  1082. }
  1083.  
  1084. ptransfer(direction, bytes, t0, t1)
  1085.     char *direction;
  1086.     long bytes;
  1087.     struct timeval *t0, *t1;
  1088. {
  1089.     struct timeval td;
  1090.     float s, bs;
  1091.  
  1092.     if (verbose) {
  1093.         tvsub(&td, t1, t0);
  1094.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1095. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1096.         bs = bytes / nz(s);
  1097.         printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
  1098.             bytes, direction, s, bs / 1024.);
  1099.     }
  1100. }
  1101.  
  1102. /*tvadd(tsum, t0)
  1103.     struct timeval *tsum, *t0;
  1104. {
  1105.  
  1106.     tsum->tv_sec += t0->tv_sec;
  1107.     tsum->tv_usec += t0->tv_usec;
  1108.     if (tsum->tv_usec > 1000000)
  1109.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1110. } */
  1111.  
  1112. tvsub(tdiff, t1, t0)
  1113.     struct timeval *tdiff, *t1, *t0;
  1114. {
  1115.  
  1116.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1117.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1118.     if (tdiff->tv_usec < 0)
  1119.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1120. }
  1121.  
  1122. void
  1123. psabort()
  1124. {
  1125.     extern int abrtflag;
  1126.  
  1127.     abrtflag++;
  1128. }
  1129.  
  1130. pswitch(flag)
  1131.     int flag;
  1132. {
  1133.     extern int proxy, abrtflag;
  1134.     sig_t oldintr;
  1135.     static struct comvars {
  1136.         int connect;
  1137.         char name[MAXHOSTNAMELEN];
  1138.         struct sockaddr_in mctl;
  1139.         struct sockaddr_in hctl;
  1140.         FILE *in;
  1141.         FILE *out;
  1142.         int tpe;
  1143.         int curtpe;
  1144.         int cpnd;
  1145.         int sunqe;
  1146.         int runqe;
  1147.         int mcse;
  1148.         int ntflg;
  1149.         char nti[17];
  1150.         char nto[17];
  1151.         int mapflg;
  1152.         char mi[MAXPATHLEN];
  1153.         char mo[MAXPATHLEN];
  1154.     } proxstruct, tmpstruct;
  1155.     struct comvars *ip, *op;
  1156.  
  1157.     abrtflag = 0;
  1158.     oldintr = signal(SIGINT, psabort);
  1159.     if (flag) {
  1160.         if (proxy)
  1161.             return;
  1162.         ip = &tmpstruct;
  1163.         op = &proxstruct;
  1164.         proxy++;
  1165.     } else {
  1166.         if (!proxy)
  1167.             return;
  1168.         ip = &proxstruct;
  1169.         op = &tmpstruct;
  1170.         proxy = 0;
  1171.     }
  1172.     ip->connect = connected;
  1173.     connected = op->connect;
  1174.     if (hostname) {
  1175.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1176.         ip->name[strlen(ip->name)] = '\0';
  1177.     } else
  1178.         ip->name[0] = 0;
  1179.     hostname = op->name;
  1180.     ip->hctl = hisctladdr;
  1181.     hisctladdr = op->hctl;
  1182.     ip->mctl = myctladdr;
  1183.     myctladdr = op->mctl;
  1184.     ip->in = cin;
  1185.     cin = op->in;
  1186.     ip->out = cout;
  1187.     cout = op->out;
  1188.     ip->tpe = type;
  1189.     type = op->tpe;
  1190.     ip->curtpe = curtype;
  1191.     curtype = op->curtpe;
  1192.     ip->cpnd = cpend;
  1193.     cpend = op->cpnd;
  1194.     ip->sunqe = sunique;
  1195.     sunique = op->sunqe;
  1196.     ip->runqe = runique;
  1197.     runique = op->runqe;
  1198.     ip->mcse = mcase;
  1199.     mcase = op->mcse;
  1200.     ip->ntflg = ntflag;
  1201.     ntflag = op->ntflg;
  1202.     (void) strncpy(ip->nti, ntin, 16);
  1203.     (ip->nti)[strlen(ip->nti)] = '\0';
  1204.     (void) strcpy(ntin, op->nti);
  1205.     (void) strncpy(ip->nto, ntout, 16);
  1206.     (ip->nto)[strlen(ip->nto)] = '\0';
  1207.     (void) strcpy(ntout, op->nto);
  1208.     ip->mapflg = mapflag;
  1209.     mapflag = op->mapflg;
  1210.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1211.     (ip->mi)[strlen(ip->mi)] = '\0';
  1212.     (void) strcpy(mapin, op->mi);
  1213.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1214.     (ip->mo)[strlen(ip->mo)] = '\0';
  1215.     (void) strcpy(mapout, op->mo);
  1216.     (void) signal(SIGINT, oldintr);
  1217.     if (abrtflag) {
  1218.         abrtflag = 0;
  1219.         signal(SIGINT, psabort); /*(*oldintr)();*/
  1220.     }
  1221. }
  1222.  
  1223. jmp_buf ptabort;
  1224. int ptabflg;
  1225.  
  1226. void
  1227. abortpt()
  1228. {
  1229.     printf("\n");
  1230.     (void) fflush(stdout);
  1231.     ptabflg++;
  1232.     mflag = 0;
  1233.     abrtflag = 0;
  1234.     longjmp(ptabort, 1);
  1235. }
  1236.  
  1237. proxtrans(cmd, local, remote)
  1238.     char *cmd, *local, *remote;
  1239. {
  1240.     sig_t oldintr;
  1241.     int secndflag = 0, prox_type, nfnd;
  1242.     extern jmp_buf ptabort;
  1243.     char *cmd2;
  1244.     /*struct*/ fd_set mask;
  1245.     void abortpt();
  1246.  
  1247.     if (strcmp(cmd, "RETR"))
  1248.         cmd2 = "RETR";
  1249.     else
  1250.         cmd2 = runique ? "STOU" : "STOR";
  1251.     if ((prox_type = type) == 0) {
  1252.         if (unix_server && unix_proxy)
  1253.             prox_type = TYPE_I;
  1254.         else
  1255.             prox_type = TYPE_A;
  1256.     }
  1257.     if (curtype != prox_type)
  1258.         changetype(prox_type, 1);
  1259.     if (command("PASV") != COMPLETE) {
  1260.         printf("proxy server does not support third party transfers.\n");
  1261.         return;
  1262.     }
  1263.     pswitch(0);
  1264.     if (!connected) {
  1265.         printf("No primary connection\n");
  1266.         pswitch(1);
  1267.         code = -1;
  1268.         return;
  1269.     }
  1270.     if (curtype != prox_type)
  1271.         changetype(prox_type, 1);
  1272.     if (command("PORT %s", pasv) != COMPLETE) {
  1273.         pswitch(1);
  1274.         return;
  1275.     }
  1276.     if (setjmp(ptabort))
  1277.         goto abort;
  1278.     oldintr = signal(SIGINT, abortpt);
  1279.     if (command("%s %s", cmd, remote) != PRELIM) {
  1280.         (void) signal(SIGINT, oldintr);
  1281.         pswitch(1);
  1282.         return;
  1283.     }
  1284.     sleep(2);
  1285.     pswitch(1);
  1286.     secndflag++;
  1287.     if (command("%s %s", cmd2, local) != PRELIM)
  1288.         goto abort;
  1289.     ptflag++;
  1290.     (void) getreply(0);
  1291.     pswitch(0);
  1292.     (void) getreply(0);
  1293.     (void) signal(SIGINT, oldintr);
  1294.     pswitch(1);
  1295.     ptflag = 0;
  1296.     printf("local: %s remote: %s\n", local, remote);
  1297.     return;
  1298. abort:
  1299.     (void) signal(SIGINT, SIG_IGN);
  1300.     ptflag = 0;
  1301.     if (strcmp(cmd, "RETR") && !proxy)
  1302.         pswitch(1);
  1303.     else if (!strcmp(cmd, "RETR") && proxy)
  1304.         pswitch(0);
  1305.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1306.         if (command("%s %s", cmd2, local) != PRELIM) {
  1307.             pswitch(0);
  1308.             if (cpend)
  1309.                 abort_remote((FILE *) NULL);
  1310.         }
  1311.         pswitch(1);
  1312.         if (ptabflg)
  1313.             code = -1;
  1314.         (void) signal(SIGINT, oldintr);
  1315.         return;
  1316.     }
  1317.     if (cpend)
  1318.         abort_remote((FILE *) NULL);
  1319.     pswitch(!proxy);
  1320.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1321.         if (command("%s %s", cmd2, local) != PRELIM) {
  1322.             pswitch(0);
  1323.             if (cpend)
  1324.                 abort_remote((FILE *) NULL);
  1325.             pswitch(1);
  1326.             if (ptabflg)
  1327.                 code = -1;
  1328.             (void) signal(SIGINT, oldintr);
  1329.             return;
  1330.         }
  1331.     }
  1332.     if (cpend)
  1333.         abort_remote((FILE *) NULL);
  1334.     pswitch(!proxy);
  1335.     if (cpend) {
  1336.         FD_ZERO(&mask);
  1337.         FD_SET(fileno(cin), &mask);
  1338.         if ((nfnd = empty(&mask, 10)) <= 0) {
  1339.             if (nfnd < 0) {
  1340.                 perror("abort");
  1341.             }
  1342.             if (ptabflg)
  1343.                 code = -1;
  1344.             lostpeer();
  1345.         }
  1346.         (void) getreply(0);
  1347.         (void) getreply(0);
  1348.     }
  1349.     if (proxy)
  1350.         pswitch(0);
  1351.     pswitch(1);
  1352.     if (ptabflg)
  1353.         code = -1;
  1354.     (void) signal(SIGINT, oldintr);
  1355. }
  1356.  
  1357. reset()
  1358. {
  1359.     /*struct*/ fd_set mask;
  1360.     int nfnd = 1;
  1361.  
  1362.     FD_ZERO(&mask);
  1363.     while (nfnd > 0) {
  1364.         FD_SET(fileno(cin), &mask);
  1365.         if ((nfnd = empty(&mask,0)) < 0) {
  1366.             perror("reset");
  1367.             code = -1;
  1368.             lostpeer();
  1369.         }
  1370.         else if (nfnd) {
  1371.             (void) getreply(0);
  1372.         }
  1373.     }
  1374. }
  1375.  
  1376. char *
  1377. gunique(local)
  1378.     char *local;
  1379. {
  1380.     static char new[MAXPATHLEN];
  1381.     char *cp = rindex(local, '/');
  1382.     int d, count=0;
  1383.     char ext = '1';
  1384.  
  1385.     if (cp)
  1386.         *cp = '\0';
  1387.     d = access(cp ? local : ".", 2);
  1388.     if (cp)
  1389.         *cp = '/';
  1390.     if (d < 0) {
  1391.         fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
  1392.         return((char *) 0);
  1393.     }
  1394.     (void) strcpy(new, local);
  1395.     cp = new + strlen(new);
  1396.     *cp++ = '.';
  1397.     while (!d) {
  1398.         if (++count == 100) {
  1399.             printf("runique: can't find unique file name.\n");
  1400.             return((char *) 0);
  1401.         }
  1402.         *cp++ = ext;
  1403.         *cp = '\0';
  1404.         if (ext == '9')
  1405.             ext = '0';
  1406.         else
  1407.             ext++;
  1408.         if ((d = access(new, 0)) < 0)
  1409.             break;
  1410.         if (ext != '0')
  1411.             cp--;
  1412.         else if (*(cp - 2) == '.')
  1413.             *(cp - 1) = '1';
  1414.         else {
  1415.             *(cp - 2) = *(cp - 2) + 1;
  1416.             cp--;
  1417.         }
  1418.     }
  1419.     return(new);
  1420. }
  1421.  
  1422. abort_remote(din)
  1423. FILE *din;
  1424. {
  1425.     char buf[BUFSIZ];
  1426.     int nfnd;
  1427.     /*struct*/ fd_set mask;
  1428.  
  1429.     /*
  1430.      * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
  1431.      * after urgent byte rather than before as is protocol now
  1432.      */
  1433.     sprintf(buf, "%c%c%c", IAC, IP, IAC);
  1434.     if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
  1435.         perror("abort");
  1436.     fprintf(cout,"%cABOR\r\n", DM);
  1437.     (void) fflush(cout);
  1438.     FD_ZERO(&mask);
  1439.     FD_SET(fileno(cin), &mask);
  1440.     if (din) { 
  1441.         FD_SET(fileno(din), &mask);
  1442.     }
  1443.     if ((nfnd = empty(&mask, 10)) <= 0) {
  1444.         if (nfnd < 0) {
  1445.             perror("abort");
  1446.         }
  1447.         if (ptabflg)
  1448.             code = -1;
  1449.         lostpeer();
  1450.     }
  1451.     if (din && FD_ISSET(fileno(din), &mask)) {
  1452.         while (read(fileno(din), buf, BUFSIZ) > 0)
  1453.             /* LOOP */;
  1454.     }
  1455.     if (getreply(0) == ERROR && code == 552) {
  1456.         /* 552 needed for nic style abort */
  1457.         (void) getreply(0);
  1458.     }
  1459.     (void) getreply(0);
  1460. }
  1461.